using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Net.NetworkInformation;
using System.Xml;
using servermon_library;

namespace servermon
{
	public partial class Main : Form
	{
		private Label notConnected = new Label();
		private Server[] servers;
		private ServerButton[] buttons;
		private ServerManager serverManager;
		private BackgroundWorker[] workers;

		public Main()
		{
			InitializeComponent();
			// this label is the only one that doesn't belong to the flowpanel yet is placed inside it.
			notConnected.Text = "Press 'start connection' to begin monitoring";
			notConnected.Location = new Point(75, 200);
			notConnected.BackColor = Color.FromName("LightGoldenrodYellow");
			notConnected.Width = 300;
			notConnected.Font = new Font("Verdana", 12);
			this.Controls.Add(notConnected);
			notConnected.BringToFront();
		}

		private void btnConnect_Click(object sender, EventArgs e)
		{// populating servers + visual changes when whe hit the "connect" button
			if (btnConnect.Text == "Start connection")
			{
				notConnected.Visible = false;
				groupBox1.Enabled = true;
				populateServers();
				btnConnect.Text = "Stop connection";
			}
			else
			{
				btnConnect.Text = "Start connection";
				groupBox1.Enabled = false;
				cleanData();
				notConnected.Visible = true;
			}
		}

		private void populateServers()
		{
			try
			{
				Int16 counter = 0;
				serverManager = new ServerManager();
				servers = serverManager.GetServers();
				buttons = new ServerButton[servers.Length];
				ServerButton button;
				workers = new BackgroundWorker[servers.Length];
				foreach (Server server in servers)
				{
					// create an icon for each server, then assign an eventhandler + backgroundworker for each.
					button = new ServerButton(server.servername, server.serverid, Color.Gray, server.serverip);
					buttons[counter] = button;
					flpServers.Controls.Add(button);
					button.Click += new EventHandler(this.button_Click);
					workers[counter] = new BackgroundWorker();
					workers[counter].DoWork += new DoWorkEventHandler(backGroundWorker_DoWork);
					counter++;
				}

				timer1.Enabled = true;
			}
			catch (Exception ex)
			{
				MessageBox.Show(ex.Message);
			}
		}

		// each server has it's own backgroundworker
		private void backGroundWorker_DoWork(Object sender, DoWorkEventArgs e)
		{
			ServerButton button = (ServerButton)e.Argument;
			PingReply pingReply = NetworkManager.Ping(button.server_ip);
			// change color depending on the status
			if (pingReply.Status == IPStatus.Success)
			{
				if (pingReply.RoundtripTime < 1000)
				{
					button.backgroundColor = Color.LightGreen;
				}
				else
				{
					button.backgroundColor = Color.DarkOrange;
				}
				serverManager.UpdateLastSeen(button.id, DateTime.Now.ToLongTimeString());
			}
			else
			{
				button.backgroundColor = Color.Red;
			}
			button.Invalidate();
		}

		// fired when you click on a serverbutton
		private void button_Click(object sender, EventArgs e)
		{
			ServerButton button = (ServerButton)sender;
			DetailWindow detailWindow = new DetailWindow(serverManager.GetServerById(button.id));
			detailWindow.Show();
		}

		// the timer checks the status of each server at certain intervals
		private void timer1_Tick(object sender, EventArgs e)
		{
			// first tick should happen almost immediatly, then every 10 seconds
			if (timer1.Interval == 500)
			{
				timer1.Interval = 10000;
			}

			Int16 counter = 0;
			foreach (BackgroundWorker worker in workers)
			{
				worker.RunWorkerAsync(buttons[counter]);
				counter++;
			}
		}

		public void window_Update()// refresh the entire field
		{
			cleanData();
			timer1.Interval = 500;
			populateServers();
		}

		private void btnAddServer_Click(object sender, EventArgs e)
		{
			AddServerWindow addServerWindow = new AddServerWindow(serverManager, this);
			addServerWindow.Show();
		}

		private void cleanData() // clean up the serverbuttons and their assigned backgroundworkers
		{
			foreach (ServerButton button in buttons)
			{
				button.Dispose();
			}
			foreach (BackgroundWorker worker in workers)
			{
				worker.Dispose();
			}
		}

		private void btnRemServer_Click(object sender, EventArgs e)
		{
			RemServerWindow remServerWindow = new RemServerWindow(serverManager, this);
			remServerWindow.Show();
		}

		// export info to XML
		private void btnExport_Click(object sender, EventArgs e)
		{
			SaveFileDialog filedialog = new SaveFileDialog();
			filedialog.Filter = "Xml files (*.xml)|*.xml";
			filedialog.FilterIndex = 2;
			filedialog.RestoreDirectory = true;
			if (filedialog.ShowDialog() == DialogResult.OK)
			{
				if (filedialog.FileName != null)
				{
					XmlTextWriter xmlWriter = new XmlTextWriter(filedialog.FileName, System.Text.Encoding.UTF8);
					xmlWriter.Formatting = Formatting.Indented;
					xmlWriter.WriteProcessingInstruction("xml", "version='1.0' encoding='UTF-8'");
					xmlWriter.WriteStartElement("Root");
					xmlWriter.Close();

					XmlDocument xmlDoc = new XmlDocument();
					xmlDoc.Load(filedialog.FileName);
					XmlNode root = xmlDoc.DocumentElement;
					XmlText textNode;
					XmlElement serverNode, idNode, nameNode, addressNode;
					foreach (Server server in servers)
					{
						serverNode = xmlDoc.CreateElement("Server");
						idNode = xmlDoc.CreateElement("Id");
						textNode = xmlDoc.CreateTextNode(Convert.ToString(server.serverid));
						idNode.AppendChild(textNode);
						nameNode = xmlDoc.CreateElement("Name");
						textNode = xmlDoc.CreateTextNode(server.servername);
						nameNode.AppendChild(textNode);
						addressNode = xmlDoc.CreateElement("Address");
						textNode = xmlDoc.CreateTextNode(server.serverip);
						addressNode.AppendChild(textNode);
						serverNode.AppendChild(idNode);
						serverNode.AppendChild(nameNode);
						serverNode.AppendChild(addressNode);
						root.AppendChild(serverNode);
					}

					xmlDoc.Save(filedialog.FileName);
				}
			}
		}
	}
}